#include "LFilePack.h"
#include <stdio.h>
#include <iostream>
#include <ios>
#include <fstream>

#include "LDirEnum.h"
#include <direct.h>
#include <stdlib.h>
#include <stdio.h>

class CLDirFPBuilder : public IDirEnumListenner
{
public:
	CLFilePack* m_pPack;
	int         m_Rate;
	wstring     m_BaseDir;
public:
	bool onFindFile(xDirEnumItem& item)
	{
		wstring name = L"";
		if( item.m_FullName[m_BaseDir.length()] == '/')
			name = (item.m_FullName.c_str() + m_BaseDir.length() + 1);
		else
			name = (item.m_FullName.c_str() + m_BaseDir.length() );

		if(item.m_isDir)
		{
			m_pPack->__insert_file( name.c_str(), item.m_FullName.c_str(), lfpdt_dir);
		}
		else
		{
			m_pPack->__insert_file( name.c_str(), item.m_FullName.c_str());
		}
		return true;
	}
};


CLFilePack::CLFilePack()
{
	m_eMode      = e_LRead;
	m_pHashTable = NULL;
}


CLFilePack::~CLFilePack()
{
	delete m_pHashTable;
	for ( size_t i=0; i<m_listDataEntry.size(); i++ )
	{

	}
	m_listDataEntry.clear();
}


bool CLFilePack::open(const wchar_t* file_name, LOpenMode eOpenMode, bool bCreate )
{
	if(file_name == NULL)
		return false;


	m_eMode = eOpenMode;
	if ( file_exist(file_name) && eOpenMode == e_LRead )
	{
		bool ret =  __open_for_read(file_name);
		if(ret) 
			wcscpy(m_file_name,file_name);
		return ret;
	}
	if( eOpenMode != e_LRead && bCreate )
	{
		if ( file_exist(file_name) == false )
		{
		}
		/// init hash table size 
		return create(file_name,128);
	}
	return true;
}


bool CLFilePack::save()
{
	ofstream file;
	file.open(m_file_name , ios::binary);
	if(file.fail())
		return false;

	_fill_header();
	bool bRet = _write_data_to_stream(file);
	file.close();
	return bRet;
}

bool CLFilePack::addFile( const wchar_t* file_name)
{
	return __insert_file( NULL, file_name, lfpdt_file, 100 );
	
}

bool CLFilePack::create(const wchar_t* file_name,int hash_table_size)
{
	m_eMode = e_LWrite;
	//__init_file_header_data();
	__init_hash_table(hash_table_size);
	wcsncpy(m_file_name,file_name,FILENAMELENGTH);
	return true;
}


bool CLFilePack::pack_dir(const wchar_t* dir_name)
{
	if ( NULL == dir_name )
		return false;
	m_BaseDir = dir_name;
	CLDirFPBuilder builder;
	builder.m_BaseDir = dir_name;
	builder.m_pPack = this;
	xDirEnum enumDir;
	enumDir.addListenner(&builder);
	enumDir.enumDir(dir_name,true);
	return true;
}

void create_all_dir(const wchar_t* bas_dir,const wchar_t* file)
{
	wchar_t dir_name[128];
	for(int i = 0 ; i < (int) wcslen(file) ; ++i)
	{
		if(file[i] == '/' || file[i] == '\\')
		{
			wcsncpy(dir_name,file,128);
			dir_name[i] = 0;
			wstring dir_full_name = std::wstring(bas_dir) + dir_name;

#ifdef _WIN32
			_wmkdir(dir_full_name.c_str());
#else

			//mkdir(mbsDirName,0777);
#endif

		}
	}
}

bool CLFilePack::unpack(const wchar_t* obj_dir)
{
	if ( NULL == obj_dir )
		return false;
	ifstream  file;
	file.open(m_file_name , ios::binary);
	if(file.fail())
		return false;


	wchar_t _bas_dir[128];
	wcscpy(_bas_dir,obj_dir );
	int len = (int)wcslen(_bas_dir);
	for(int i =0 ; i < len ; i++)
	{
		if(_bas_dir[i] == '\\') _bas_dir[i] = '/';
	}
	if(_bas_dir[len-1] != '/')
		wcscat(_bas_dir,L"/");  
	/// create the  root dir 
	create_all_dir(L"",_bas_dir);
	for (size_t i=0; i<m_listDataEntry.size(); i++ )
	{
		sFPDataEntry & entry = m_listDataEntry[i];
		create_all_dir(_bas_dir,entry.m_DataEntryInfo.m_name);
		if ( 0 != entry.m_DataEntryInfo.m_nLength ) /// not dir , must be file or data buffer 
		{
			wstring file_name = std::wstring(_bas_dir) + entry.m_DataEntryInfo.m_name;
			_unpack_data(file, file_name.c_str(), entry.m_DataEntryInfo);
		}
	}
	return true;
}

bool CLFilePack::unwrapBuffer( const wchar_t* name, char** ppBuffer )
{
	if ( NULL == name )
		return false;
	if ( NULL != *ppBuffer )
		return false;

	return true;
}


bool CLFilePack::unwrapFile( const wchar_t* name, const wchar_t* file_name )
{
	return false;
}

